######################################################################
# Time-stamp: <05/02/14 14:25:37 ostolop>
#
# Routines to build EPC output XML documents
######################################################################
package EP::Common::Query::OutputBuilder;
use strict;

chomp ( my $date = `date` );

use XML::LibXML;
use EP::Common::Query::ErrorBuilder;

my $epc_output_XML = <<__EPCOUTPUTXML__;
<?xml version="1.0"?><epc_output/>
__EPCOUTPUTXML__

=head1 NAME

EP_UI_XML::OutputBuilder - build the EPC output and error XML
documents from a component's HTML output

=head1 SYNOPSIS

C<my ($output_doc, $error_doc) = OutputBuilder::build_output ( $action, $res->content );>

Here C<$action> is the C<<action>> element of the EPC XML definition,
and C<$res->content> is the HTML content of a component's execution
output.

=head1 DESCRIPTION

TODO

=head1 METHODS

=over

=item build_output

Produces the output XML document and an error document (hopefully
without any errors in it).

=cut

sub build_output {
  my ($action, $response) = @_;

  my $parser = new XML::LibXML;
  my $doc = $parser->parse_string ( $response );

  my $err = new EP::Common::Query::ErrorBuilder;

  $doc->getDocumentElement()->setAttribute("title", $action->findvalue('ancestor::component/@title'));
  foreach ( @{$doc->findnodes ( "/epc_output/error" )} ) {
    $err->getDocumentElement()->appendChild ( $_ );
  }

  foreach my $output ( @{$doc->findnodes ( "/epc_output/output" )} ) {
    my $name = $output->getAttribute ( "name" );

    my ($action_output) = $action->findnodes ( "output[\@name='$name']" );

    if ( $action_output ) {
      $output->setAttribute ( "action_output", "1" );
      $output->setAttribute ( "display", "hidden" ) if $action_output->findvalue ( '@display' ) eq "hidden";
      $output->setAttribute ( "label", $action_output->findvalue ( '@label' ) ) if $action_output->findvalue ( '@label' );
      $output->setAttribute ( "type", $action_output->findvalue ( '@type' ) ) if $action_output->findvalue ( '@type' );
    } else {
      $output->setAttribute ( "action_output", "0" );
      $output->setAttribute ( "display", "hidden" );
    }
  }

  if ( $@ ) {
    error ( $@ );
    die "Couldn't parse response XML! ($@)";
  }

  return ( $doc, $err );
}

sub create_output {
  my ( $doc, $err, $response, $output_node ) = @_;

  my $regex = $output_node->findvalue ( '@match_regex' );
  my $name = $output_node->findvalue ( '@name' );
  my $label = $output_node->findvalue ( '@label' );
  my $type = $output_node->findvalue( '@type' );
  my $display = $output_node->findvalue ( '@display' );

  my $output = $doc->createElement( "output" );

  $output->setAttribute ( "name", $name );
  $output->setAttribute ( "label", $label  );
  $output->setAttribute( "type", $type );
  $output->setAttribute ( "display", $display );

  my $value = $doc->createElement("value");

  my ( $found_output ) = $$response =~ /$regex/is;
  my $value_text = "";

  if ( $found_output ) {
    $output->setAttribute ( "matched", 1 );
    $value_text = $doc->createTextNode ( $found_output );
  } else {
    $output->setAttribute ( "matched", 0 );
    $value_text = $doc->createTextNode ( "Output not found!" );

#    &process_errors($output_node, $err, $response, $name, $label);
  }

  $value->appendChild ( $value_text );
  $output->appendChild ( $value );

  return $output;
}

sub process_errors {
  my ($output_node, $err, $response, $name, $label) = @_;

  my @err_nodes = $output_node->findnodes( 'match_errors' );

  if ( scalar(@err_nodes) != 0 ) {
    my ($count_err) = 0;
    foreach my $err_node ( @err_nodes ) {
      my $err_regex = $err_node->findvalue( '@regex' );
      my $err_code = $err_node->findvalue( '@err_code' );

      if ( $$response =~ /$err_regex/i ) {
	$err->add_error ( $1, $err_code, 3 );
	$count_err++;
      }
    }
	
    if ( $count_err == 0 ) {
      $err->add_error ( "An unknown error occurred, did not find $label ($name)", 0, 3 );
    }
  } else {
    $err->add_error ( "Output regex not matched for $label ($name)", 1, 3 );
  }
  return;
}

sub error {
  my $error = shift;
  print STDERR "Error in eval: ";
  if (ref $error) {
    print STDERR "msg: ", $error->getMessage();
    if (ref $error eq 'XML::Xerces::DOM_DOMException') {
      print STDERR "\n\tcode: ", $error->{code};
    }
  print STDERR "\n";
  } else {
    print STDERR $error;
  }
}

1;
